/**
 * 
 */
package org.tuestudent.grouppa;

import java.util.Date;

import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.tuestudent.grouppa.AppContext.ActiveScreens;
import org.tuestudent.grouppa.WallViewController.GetAllTopicsResponse;

import android.content.IntentSender.SendIntentException;

/**
 * @author s121170 Class that services all the views and popups of chat system
 */
public class ChatViewController extends ViewController {


    /**
     * hidden constructor, use getInstance()
     * 
     */
    private ChatViewController() {

    }

    private static ChatViewController instance;
    /**
     * ID to which all messages were read
     */
    private long lastCheckID=0;

    /**
     * for ignoring messages on first check
     */
    private boolean firstCheck=true;
    public static ChatViewController getInstance() {
        if (instance != null)
            return instance;

        instance = new ChatViewController();
        return instance;
    }

    /**
     * gets messages from the chat system
     */
    public void getAllMessages() {
        // CHECK: get message from the server
        MessageFromApp message = new MessageFromApp();
        String username = Main.getContext().currentUserName;
        message.from = username;
        message.messageType = "getAllMessagesResponse";
        message.task = "getMessages";
        message.toController = "Chat";
        String groupName = Main.getContext().getCurrentGroup();
        message.toGroup = groupName;
        message.serializedArguments = "{\"groupName\":\"" + groupName + "\"," +
        		"\"userName\":\"" + username + "\"}";
        Main.getConnection().sendMessage(message);
    }

    public class GetAllMessagesResponse {

        ChatMessage[] allMessages;
        // did operation succeed?
        boolean retrieved;
        // if the operation didn't succeed , here is why
        String errorReason;
    }

    /**
     * sends a new message to a group chat from current user
     * 
     * @param message
     *            message to be sent
     */
    public void postNewMessage(ChatMessage cmessage) {
        // TODO: send to server request to post a chat message
        // CHECK: get message from the server
        MessageFromApp message = new MessageFromApp();
        String username = Main.getContext().currentUserName;
        message.from = username;
        message.messageType = "postNewMessageResponse";
        message.task = "postNewMessage";
        message.toController = "Chat";
        String groupName = Main.getContext().getCurrentGroup();
        message.toGroup = groupName;
        message.serializedArguments = "{\"groupName\":\"" + groupName + "\"," +
                "\"author\":\"" + username+ "\"," +
                "\"text\":\"" + StringEscapeUtils.escapeJson(cmessage.text) + "\"," +
                "\"date\":\"" + ((new Date()).getTime()/1000)+ "\"," +
                        "\"idFrom\":" + lastCheckID  + "}";
        Main.getConnection().sendMessage(message);

    }

    public class PostNewMessageResponse {

        // did operation succeed?
        boolean posted;
        // if the operation didn't succeed , here is why
        String errorReason;
        ChatMessage postedMessage;
        public ChatMessage[] allMessages;
    }

    @Override
    public void onMessageReceived(MessageFromServer message) {
        AppContext ctx = Main.getContext();
        if (ctx.activeScreen != ActiveScreens.grouppaScreen
                || checkForError(message))
            return; // ignoring messages if grouppa screen is not active
        if (message.messageType.equals("getNewMessagesResponse")) {
            processGetNewMessagesResponse(message, ctx);
        } else if (message.messageType.equals("getAllMessagesResponse")) {
            processGetAllMessagesResponse(message, ctx);
        } else if (message.messageType.equals("postNewMessageResponse")) {
            processPostNewMessageResponse(message, ctx);
        }

    }

    private void processPostNewMessageResponse(MessageFromServer message,
            AppContext ctx) {
        if ( !(ctx.currentGrouppaFragment instanceof Chat))
            return;
        PostNewMessageResponse response = new PostNewMessageResponse();
        try {
            JSONObject args = new JSONObject(message.serializedArguments);
            response.posted = args.getBoolean("posted");
            response.errorReason = args.optString("reason");
            if(!response.posted)
            {
                ctx.grouppaActivity.errorPopup("Error while sending message: "+response.errorReason);
                return;
            }
            
            ChatMessage newMessage = new ChatMessage();
            newMessage.author = args.getString("author");
            newMessage.date = new Date(args.getInt("date")*1000);
            newMessage.text = args.getString("messageText");
            response.postedMessage = newMessage;
            response.allMessages = null;
            if(args.getLong("fromId") == lastCheckID)
            {
                JSONArray messages = args.getJSONArray("all_messages");
                lastCheckID = args.getLong("newId");
                ChatMessage[] newMessages = new ChatMessage[messages.length()];
                for (int i = 0; i < messages.length(); i++ ) {
                    newMessages[i] = new ChatMessage();
                    JSONObject chatMessage = messages.getJSONObject(i);
                    newMessages[i].author = chatMessage.getString("author");
                    newMessages[i].date = new Date(chatMessage.getLong("time") * 1000);
                    newMessages[i].text =
                            StringEscapeUtils.unescapeJson(chatMessage.getString("text"));
                }
                response.allMessages = newMessages;
            }
            ((Chat) ctx.currentGrouppaFragment)
                .onPostNewMessageResponse(response);
        } catch (Exception ex) {
            ctx.grouppaActivity.errorPopup("Error: " + ex.getMessage());
        }
        
    }

    private void processGetAllMessagesResponse(MessageFromServer message,
            AppContext ctx) {
        if ( !(ctx.currentGrouppaFragment instanceof Chat))
            return;
        GetNewMessagesResponse response = new GetNewMessagesResponse();
        try {
            JSONObject args = new JSONObject(message.serializedArguments);
            response.retrieved = args.getBoolean("retrieved");
            response.errorReason = args.optString("error_reason");
            JSONArray messages = args.getJSONArray("all_messages");
            lastCheckID = args.getLong("newId");
            ChatMessage[] newMessages = new ChatMessage[messages.length()];
            for (int i = 0; i < messages.length(); i++ ) {
                newMessages[i] = new ChatMessage();
                JSONObject chatMessage = messages.getJSONObject(i);
                newMessages[i].author = chatMessage.getString("author");
                newMessages[i].date = new Date(chatMessage.getLong("time") * 1000);
                newMessages[i].text =
                        StringEscapeUtils.unescapeJson(chatMessage.getString("text"));
            }
            response.allMessages = newMessages;
            ((Chat) ctx.currentGrouppaFragment)
                    .onNewMessages(response);
        } catch (Exception ex) {
            ctx.grouppaActivity.errorPopup("Error: " + ex.getMessage());
        }
        
    }

    private void processGetNewMessagesResponse(MessageFromServer message,
            AppContext ctx) {
        if ( !(ctx.currentGrouppaFragment instanceof Chat))
        {
            try {
                JSONObject args = new JSONObject(message.serializedArguments);
                lastCheckID = args.getLong("newId");
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(firstCheck)
                firstCheck = false;
            else
                showNotification("Grouppa Chat Message", "There is a new chat message for you from group "+ctx.getCurrentGroup(), ctx.getCurrentGroup(), notificationIds.chatMessageNotification);
            return;
        }
        GetAllMessagesResponse response = new GetAllMessagesResponse();
        try {
            JSONObject args = new JSONObject(message.serializedArguments);
            response.retrieved = args.getBoolean("retrieved");
            response.errorReason = args.optString("error_reason");
            if(response.retrieved && args.getInt("fromId") != lastCheckID)
                return;
            lastCheckID = args.getLong("newId");
            JSONArray messages = args.getJSONArray("all_messages");
            ChatMessage[] newMessages = new ChatMessage[messages.length()];
            for (int i = 0; i < messages.length(); i++ ) {
                newMessages[i] = new ChatMessage();
                JSONObject chatMessage = messages.getJSONObject(i);
                newMessages[i].author = chatMessage.getString("author");
                newMessages[i].date = new Date(chatMessage.getLong("time") * 1000);
                newMessages[i].text =
                        StringEscapeUtils.unescapeJson(chatMessage.getString("text"));
            }
            response.allMessages = newMessages;
            ((Chat) ctx.currentGrouppaFragment)
                    .onGetAllMessagesResponse(response);
        } catch (Exception ex) {
            ctx.grouppaActivity.errorPopup("Error: " + ex.getMessage());
        }
        
    }

    /**
     * gets messages from the chat system
     */
    public void getNewMessages() {
        // CHECK: get message from the server
        MessageFromApp message = new MessageFromApp();
        String username = Main.getContext().currentUserName;
        message.from = username;
        message.messageType = "getNewMessagesResponse";
        message.task = "getNewMessages";
        message.toController = "Chat";
        String groupName = Main.getContext().getCurrentGroup();
        message.toGroup = groupName;
        message.serializedArguments = "{\"groupName\":\"" + groupName + "\"," +
                "\"userName\":\"" + username + "\"," +
                "\"idFrom\":" + lastCheckID + "}";
        Main.getConnection().sendMessage(message);
    }

    public class GetNewMessagesResponse {

        ChatMessage[] allMessages;
        // did operation succeed?
        boolean retrieved;
        // if the operation didn't succeed , here is why
        String errorReason;
    }

    @Override
    public void reset() {
        lastCheckID = 0;
        firstCheck = true;
    }

}
